package com.huangd.platform.common.utils;

import com.huangd.platform.common.exception.RRException;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.URI;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * http请求封装类
 * 
 * @author wing
 * 
 */
public class HttpClientUtil {

	public static final int DEFAULT_CONNECT_TIMEOUT = 2000;
	public static final int DEFAULT_SOCKET_TIMEOUT = 30000;

	public static String http(HttpRequestBase method, String encoding) throws Exception {
		encoding = encoding == null ? "utf8" : encoding;

		CloseableHttpClient client = HttpClients.createDefault();
		try {
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(DEFAULT_SOCKET_TIMEOUT).setConnectTimeout(DEFAULT_CONNECT_TIMEOUT).build();
			method.setConfig(requestConfig);

			HttpResponse response = client.execute(method);
			return EntityUtils.toString(response.getEntity(), "utf8");
		} finally {
			IOUtils.close(client);
		}
	}

	public static HttpResponse httpResponse(HttpRequestBase method, String encoding) throws Exception {
		encoding = encoding == null ? "utf8" : encoding;

		CloseableHttpClient client = HttpClients.createDefault();
		try {
			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(DEFAULT_SOCKET_TIMEOUT).setConnectTimeout(DEFAULT_CONNECT_TIMEOUT).build();
			method.setConfig(requestConfig);

			HttpResponse response = client.execute(method);
			return response;
		} finally {
			IOUtils.close(client);
		}
	}

	public static String getData(String url, String encoding) {
		try {
			return getData(url, encoding, DEFAULT_CONNECT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RRException("访问http出错");
		}
	}

	public static String getData(String url, String encoding, int connectTimeout, int socketTimeout) throws Exception {

		encoding = encoding == null ? "utf8" : encoding;

		CloseableHttpClient client = HttpClients.createDefault();
		try {
			HttpGet method = new HttpGet(url);

			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
			method.setConfig(requestConfig);

			HttpResponse response = client.execute(method);

			String result = EntityUtils.toString(response.getEntity(), encoding);
			return result;
		} finally {
			client.close();
		}
	}

	public static HttpResponse getData(CloseableHttpClient client, String url, String encoding) throws Exception {

		return getData(client, url, encoding, DEFAULT_CONNECT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
	}

	public static HttpResponse getData(CloseableHttpClient client, String url, String encoding, int connectTimeout, int socketTimeout) throws Exception {

		encoding = encoding == null ? "utf8" : encoding;

		HttpGet method = new HttpGet(url);

		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
		method.setConfig(requestConfig);

		HttpResponse response = client.execute(method);
		return response;
	}

	public static String postData(String url, String data, String encoding) throws Exception {

		return postData(url, data, encoding, DEFAULT_CONNECT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
	}

	public static String postData(String url, String data, String encoding, int connectTimeout, int socketTimeout) throws Exception {

		encoding = encoding == null ? "utf8" : encoding;

		CloseableHttpClient client = HttpClients.createDefault();
		try {
			HttpPost method = new HttpPost(url);

			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
			method.setConfig(requestConfig);

			StringEntity entity = new StringEntity(data, encoding);
			method.setEntity(entity);
			HttpResponse response = client.execute(method);
			String result = EntityUtils.toString(response.getEntity(), encoding);
			return result;
		} finally {
			client.close();
		}
	}

	public static HttpResponse postData(CloseableHttpClient client, String url, String data, String encoding) throws Exception {

		return postData(client, url, data, encoding, DEFAULT_CONNECT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
	}

	public static HttpResponse postData(CloseableHttpClient client, String url, String data, String encoding, int connectTimeout, int socketTimeout) throws Exception {

		encoding = encoding == null ? "utf8" : encoding;

		HttpPost method = new HttpPost(url);

		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
		method.setConfig(requestConfig);

		StringEntity entity = new StringEntity(data, encoding);
		method.setEntity(entity);
		HttpResponse response = client.execute(method);
		return response;
	}

	public static String postData(String url, Map<String, String> params, String encoding) throws Exception {

		return postData(url, params, encoding, DEFAULT_CONNECT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
	}

	public static String postData(String url, Map<String, String> params, String encoding, int connectTimeout, int socketTimeout) throws Exception {

		encoding = encoding == null ? "utf8" : encoding;

		CloseableHttpClient client = HttpClients.createDefault();
		try {
			HttpPost method = new HttpPost(url);

			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
			method.setConfig(requestConfig);

			if (params != null && params.size() > 0) {
				List<NameValuePair> list = new ArrayList<NameValuePair>();
				for (Entry<String, String> entry : params.entrySet()) {
					list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
				}
				method.setEntity(new UrlEncodedFormEntity(list, encoding));
			}

			HttpResponse response = client.execute(method);

			String result = EntityUtils.toString(response.getEntity(), encoding);
			return result;
		} finally {
			client.close();
		}
	}

	public static HttpResponse postData(CloseableHttpClient client, String url, Map<String, String> params, String encoding) throws Exception {

		return postData(client, url, params, encoding, DEFAULT_CONNECT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
	}

	public static HttpResponse postData(CloseableHttpClient client, String url, Map<String, String> params, String encoding, int connectTimeout, int socketTimeout) throws Exception {

		encoding = encoding == null ? "utf8" : encoding;

		HttpPost method = new HttpPost(url);

		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
		method.setConfig(requestConfig);

		if (params != null && params.size() > 0) {
			List<NameValuePair> list = new ArrayList<NameValuePair>();
			for (Entry<String, String> entry : params.entrySet()) {
				list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
			}
			method.setEntity(new UrlEncodedFormEntity(list, encoding));
		}

		HttpResponse response = client.execute(method);
		return response;
	}

	public static String https(HttpRequestBase method, String encoding) throws Exception {
		encoding = encoding == null ? "utf8" : encoding;

		CloseableHttpClient client = null;
		try {
			client = createHttpsClient();

			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(DEFAULT_SOCKET_TIMEOUT).setConnectTimeout(DEFAULT_CONNECT_TIMEOUT).build();
			method.setConfig(requestConfig);

			HttpResponse response = client.execute(method);
			return EntityUtils.toString(response.getEntity(), "utf8");
		} finally {
			IOUtils.close(client);
		}
	}

	public static HttpResponse httpsResponse(HttpRequestBase method, String encoding) throws Exception {
		encoding = encoding == null ? "utf8" : encoding;

		CloseableHttpClient client = null;
		try {
			client = createHttpsClient();

			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(DEFAULT_SOCKET_TIMEOUT).setConnectTimeout(DEFAULT_CONNECT_TIMEOUT).build();
			method.setConfig(requestConfig);

			HttpResponse response = client.execute(method);
			return response;
		} finally {
			IOUtils.close(client);
		}
	}

	public static String httpsGetData(String url, String encoding) throws Exception {

		return httpsGetData(url, encoding, DEFAULT_CONNECT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
	}

	public static String httpsGetData(String url, String encoding, int connectTimeout, int socketTimeout) throws Exception {

		encoding = encoding == null ? "utf8" : encoding;

		CloseableHttpClient client = null;
		try {
			client = createHttpsClient();

			HttpGet method = new HttpGet(url);

			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
			method.setConfig(requestConfig);

			HttpResponse response = client.execute(method);

			String result = EntityUtils.toString(response.getEntity(), encoding);
			return result;
		} finally {
			IOUtils.close(client);
		}
	}

	public static HttpResponse httpsGetData(CloseableHttpClient client, String url, String encoding) throws Exception {

		return httpsGetData(client, url, encoding, DEFAULT_CONNECT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
	}

	public static HttpResponse httpsGetData(CloseableHttpClient client, String url, String encoding, int connectTimeout, int socketTimeout) throws Exception {

		encoding = encoding == null ? "utf8" : encoding;

		HttpGet method = new HttpGet(url);

		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
		method.setConfig(requestConfig);

		HttpResponse response = client.execute(method);
		return response;
	}

	public static String httpsPostData(String url, String data, String encoding) throws Exception {

		return httpsPostData(url, data, encoding, DEFAULT_CONNECT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
	}

	public static String httpsPostData(String url, String data, String encoding, int connectTimeout, int socketTimeout) throws Exception {

		encoding = encoding == null ? "utf8" : encoding;

		CloseableHttpClient client = null;
		try {
			client = createHttpsClient();

			HttpPost method = new HttpPost(url);

			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(DEFAULT_SOCKET_TIMEOUT).setConnectTimeout(DEFAULT_CONNECT_TIMEOUT).build();
			method.setConfig(requestConfig);

			StringEntity entity = new StringEntity(data, encoding);
			method.setEntity(entity);
			HttpResponse response = client.execute(method);

			String result = EntityUtils.toString(response.getEntity(), encoding);
			return result;
		} finally {
			client.close();
		}
	}

	public static HttpResponse httpsPostData(CloseableHttpClient client, String url, String data, String encoding) throws Exception {

		return httpsPostData(client, url, data, encoding, DEFAULT_CONNECT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
	}

	public static HttpResponse httpsPostData(CloseableHttpClient client, String url, String data, String encoding, int connectTimeout, int socketTimeout) throws Exception {

		encoding = encoding == null ? "utf8" : encoding;

		HttpPost method = new HttpPost(url);

		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(DEFAULT_SOCKET_TIMEOUT).setConnectTimeout(DEFAULT_CONNECT_TIMEOUT).build();
		method.setConfig(requestConfig);

		StringEntity entity = new StringEntity(data, encoding);
		method.setEntity(entity);
		HttpResponse response = client.execute(method);
		return response;
	}

	public static String httpsPostData(String url, Map<String, String> params, String encoding) throws Exception {

		return httpsPostData(url, params, encoding, DEFAULT_CONNECT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
	}

	public static String httpsPostData(String url, Map<String, String> params, String encoding, int connectTimeout, int socketTimeout) throws Exception {

		encoding = encoding == null ? "utf8" : encoding;

		CloseableHttpClient client = null;
		try {
			client = createHttpsClient();

			HttpPost method = new HttpPost(url);

			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(DEFAULT_SOCKET_TIMEOUT).setConnectTimeout(DEFAULT_CONNECT_TIMEOUT).build();
			method.setConfig(requestConfig);

			if (params != null && params.size() > 0) {
				List<NameValuePair> list = new ArrayList<NameValuePair>();
				for (Entry<String, String> entry : params.entrySet()) {
					list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
				}
				method.setEntity(new UrlEncodedFormEntity(list, encoding));
			}

			HttpResponse response = client.execute(method);

			String result = EntityUtils.toString(response.getEntity(), encoding);
			return result;
		} finally {
			client.close();
		}
	}

	public static HttpResponse httpsPostData(CloseableHttpClient client, String url, Map<String, String> params, String encoding) throws Exception {

		return httpsPostData(client, url, params, encoding, DEFAULT_CONNECT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
	}

	public static HttpResponse httpsPostData(CloseableHttpClient client, String url, Map<String, String> params, String encoding, int connectTimeout, int socketTimeout) throws Exception {

		encoding = encoding == null ? "utf8" : encoding;

		HttpPost method = new HttpPost(url);

		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(DEFAULT_SOCKET_TIMEOUT).setConnectTimeout(DEFAULT_CONNECT_TIMEOUT).build();
		method.setConfig(requestConfig);

		if (params != null && params.size() > 0) {
			List<NameValuePair> list = new ArrayList<NameValuePair>();
			for (Entry<String, String> entry : params.entrySet()) {
				list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
			}
			method.setEntity(new UrlEncodedFormEntity(list, encoding));
		}

		HttpResponse response = client.execute(method);
		return response;
	}

	public static CloseableHttpClient createHttpsClient() throws Exception {
		SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {

			@Override
			public boolean isTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
				return true;
			}
		}).build();
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);

		//设置ssl连接时的超时时间,并且该设置存在bug,修复于4.3.6版本之后
		SocketConfig sc = SocketConfig.custom().setSoTimeout(DEFAULT_SOCKET_TIMEOUT).build();
		return HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultSocketConfig(sc).build();
	}

	/**
	 * get请求带参数
	 * @param url 地址
	 * @param param   参数
	 * @param header 请求头
	 * @return
	 */
	public static String doGetHeader(String url, Map<String, String> header , Map<String, String> param) {
		// 创建Httpclient对象
		CloseableHttpClient httpclient = HttpClients.createDefault();
		String resultString = "";
		CloseableHttpResponse response = null;
		try {
			// 创建uri
			URIBuilder builder = new URIBuilder(url);
			if (param != null) {
				for (String key : param.keySet()) {
					builder.addParameter(key, param.get(key));
				}
			}
			URI uri = builder.build();
			HttpGet httpGet = new HttpGet(uri);
			if (header != null) {
				for (String key : header.keySet()) {
					httpGet.addHeader(key, header.get(key));
				}
			}
			response = httpclient.execute(httpGet);
			if (response.getStatusLine().getStatusCode() == 200) {
				resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (response != null) {
					response.close();
				}
				httpclient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return resultString;
	}

}
